home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 June: System Software / Dev.CD Jun 97 SSW.toast / What's New? / Sample Code / Toolbox / FinderDragPro / Technote.c < prev    next >
Encoding:
Text File  |  1997-04-23  |  11.0 KB  |  496 lines  |  [TEXT/CWIE]

  1.     //
  2.     //    LEGAL NOTICE
  3.     //    ============
  4.     //
  5.     //     You may incorporate this sample code into your applications
  6.     //     without restriction. This sample code has been provided "AS
  7.     //     IS" and the responsibility for its operation is 100% yours.
  8.     //     You are not permitted to redistribute the source as "Apple
  9.     //     sample code" after having made changes. If you're going to
  10.     //     re-distribute the source, we require that you make it clear
  11.     //     in the source that the code was descended from Apple sample
  12.     //     code, but that you've made changes.
  13.     //
  14.  
  15. #define OLDROUTINELOCATIONS        0
  16. #define OLDROUTINENAMES            0
  17. #define SystemSevenOrLater        1
  18.  
  19. #ifndef __ALIASES__
  20. #    include <Aliases.h>
  21. #endif
  22.  
  23. #include "Technote.h"
  24.  
  25. static pascal Size MinimumBytesForFSSpec (const FSSpec *fss)
  26. {
  27.     //
  28.     //    Some senders don't bother sending the unused bytes of the
  29.     //    file name. This function helps make sure the FSSpec is
  30.     //    minimally sane by computing the minimum number of bytes it
  31.     //    would take to store it.
  32.     //
  33.     //    THIS FUNCTION CANNOT MOVE MEMORY.
  34.     //
  35.  
  36.     return sizeof (*fss) - sizeof (fss->name) + *(fss->name) + 1;
  37. }
  38.  
  39. static pascal OSErr FSpGetDirInfo (const FSSpec *spec, CInfoPBPtr *cipbpp)
  40. {
  41.     OSErr err = noErr;
  42.  
  43.     CInfoPBPtr pbp = (CInfoPBPtr) NewPtrClear (sizeof (*pbp));
  44.  
  45.     *cipbpp = nil;
  46.  
  47.     if (!(err = MemError ( )))
  48.     {
  49.         pbp->dirInfo.ioVRefNum = spec->vRefNum;
  50.         pbp->dirInfo.ioDrDirID = spec->parID;
  51.         pbp->dirInfo.ioNamePtr = (StringPtr) spec->name;
  52.  
  53.         err = PBGetCatInfoSync (pbp);
  54.  
  55.         if (!err && !(pbp->hFileInfo.ioFlAttrib & ioDirMask))
  56.             err = dirNFErr;
  57.  
  58.         if (err)
  59.             DisposePtr ((Ptr) pbp);
  60.         else
  61.             *cipbpp = pbp;
  62.     }
  63.  
  64.     return err;
  65. }
  66.  
  67. pascal OSErr GetDirID (const FSSpec *spec, long *dirID)
  68. {
  69.     OSErr err = noErr;
  70.  
  71.     CInfoPBPtr cipbp;
  72.  
  73.     if (!(err = FSpGetDirInfo (spec,&cipbp)))
  74.     {
  75.         *dirID = cipbp->dirInfo.ioDrDirID;
  76.  
  77.         DisposePtr ((Ptr) cipbp);
  78.         if (!err) err = MemError ( );
  79.     }
  80.  
  81.     return err;
  82. }
  83.  
  84. pascal OSErr GetDropDirectory (DragReference dragRef, FSSpecPtr fssOut)
  85. {
  86.     OSErr err = noErr;
  87.  
  88.     AEDesc dropLocAlias = { typeNull, nil };
  89.  
  90.     if (!(err = GetDropLocation (dragRef,&dropLocAlias)))
  91.     {
  92.         if (dropLocAlias.descriptorType != typeAlias)
  93.             err = paramErr;
  94.         else
  95.         {
  96.             AEDesc dropLocFSS = { typeNull, nil };
  97.  
  98.             if (!(err = AECoerceDesc (&dropLocAlias,typeFSS,&dropLocFSS)))
  99.             {
  100.                 // assume MinimumBytesForFSSpec does not move memory
  101.                 FSSpecPtr fss = (FSSpecPtr) *(dropLocFSS.dataHandle);
  102.                 BlockMoveData (fss,fssOut,MinimumBytesForFSSpec(fss));
  103.                 err = AEDisposeDesc (&dropLocFSS);
  104.             }
  105.         }
  106.  
  107.         if (dropLocAlias.dataHandle)
  108.         {
  109.             OSErr err2 = AEDisposeDesc (&dropLocAlias);
  110.             if (!err) err = err2;
  111.         }
  112.     }
  113.  
  114.     return err;
  115. }
  116.  
  117. static pascal OSErr FSpGetDInfo (const FSSpec *spec, DInfo *fndrInfo)
  118. {
  119.     OSErr err = noErr;
  120.  
  121.     CInfoPBPtr cipbp;
  122.  
  123.     if (!(err = FSpGetDirInfo (spec,&cipbp)))
  124.     {
  125.         *fndrInfo = cipbp->dirInfo.ioDrUsrWds;
  126.  
  127.         DisposePtr ((Ptr) cipbp);
  128.         if (!err) err = MemError ( );
  129.     }
  130.  
  131.     return err;
  132. }
  133.  
  134. static pascal OSErr FSpSetDInfo (const FSSpec *spec, const DInfo *fndrInfo)
  135. {
  136.     OSErr err = noErr;
  137.  
  138.     CInfoPBPtr cipbp;
  139.  
  140.     if (!(err = FSpGetDirInfo (spec,&cipbp)))
  141.     {
  142.         cipbp->dirInfo.ioDrUsrWds    = *fndrInfo;
  143.         cipbp->dirInfo.ioDrDirID    = spec->parID;
  144.  
  145.         err = PBSetCatInfoSync (cipbp);
  146.  
  147.         DisposePtr ((Ptr) cipbp);
  148.         if (!err) err = MemError ( );
  149.     }
  150.  
  151.     return err;
  152. }
  153.  
  154. static pascal CreatePromisedFile
  155.     (const PromiseHFSFlavor *phfs, const FSSpec *fss, ScriptCode scriptTag)
  156. {
  157.     OSErr err = noErr;
  158.  
  159.     if (!(err = FSpCreate (fss,phfs->fileCreator,phfs->fileType,scriptTag)))
  160.     {
  161.         if (phfs->fdFlags)
  162.         {
  163.             FInfo finderInfo;
  164.  
  165.             if (!(err = FSpGetFInfo (fss,&finderInfo)))
  166.             {
  167.                 finderInfo.fdFlags = phfs->fdFlags;
  168.                 err = FSpSetFInfo (fss,&finderInfo);
  169.             }
  170.         }
  171.     }
  172.  
  173.     return err;
  174. }
  175.  
  176. static pascal CreatePromisedFolder
  177.     (const PromiseHFSFlavor *phfs, const FSSpec *fss, ScriptCode scriptTag)
  178. {
  179.     OSErr err = noErr;
  180.  
  181.     long newDirID; // scratch
  182.     if (!(err = FSpDirCreate (fss,scriptTag,&newDirID)))
  183.     {
  184.         if (phfs->fdFlags)
  185.         {
  186.             DInfo finderInfo;
  187.  
  188.             if (!(err = FSpGetDInfo (fss,&finderInfo)))
  189.             {
  190.                 finderInfo.frFlags = phfs->fdFlags;
  191.                 err = FSpSetDInfo (fss,&finderInfo);
  192.             }
  193.         }
  194.     }
  195.  
  196.     return err;
  197. }
  198.  
  199. pascal OSErr CreatePromisedFileOrFolder
  200.     (const PromiseHFSFlavor *phfs, const FSSpec *fss, ScriptCode scriptTag)
  201. {
  202.     OSErr err = noErr;
  203.  
  204.     if (phfs->promisedFlavor == kPromisedFlavorFindFile)
  205.         err = paramErr;
  206.     else if (phfs->fileType == 'fold' || phfs->fileType == 'disk')
  207.         err = CreatePromisedFolder (phfs,fss,scriptTag);
  208.     else
  209.         err = CreatePromisedFile (phfs,fss,scriptTag);
  210.  
  211.     return err;
  212. }
  213.  
  214. pascal OSErr SetPromisedHFSFlavorData
  215.     (DragReference dragRef, ItemReference itemRef,
  216.         const PromiseHFSFlavor *phfs, const FSSpec *fss)
  217. {
  218.     return SetDragItemFlavorData
  219.         (dragRef,itemRef,phfs->promisedFlavor,fss,sizeof(*fss),0);
  220. }
  221.  
  222. pascal OSErr ShouldCopyToDropLoc
  223.     (DragReference dragRef, FlavorType promisedFlavor, Boolean *shouldCopy)
  224. {
  225.     OSErr err = noErr;
  226.  
  227.     AEDesc dropLoc = { typeNull, nil };
  228.  
  229.     *shouldCopy = false;
  230.  
  231.     if (!(err = GetDropLocation (dragRef,&dropLoc)))
  232.     {
  233.         if (dropLoc.descriptorType == typeAlias)
  234.         {
  235.             // no hint or receiver missed it
  236.             *shouldCopy = true;
  237.         }
  238.         else if (dropLoc.descriptorType != typeNull)
  239.         {
  240.             // unknown drop location descriptor type
  241.             err = paramErr;
  242.         }
  243.         else if (promisedFlavor != kPromisedFlavorFindFile)
  244.         {
  245.             // null descriptor but no hint intended
  246.             err = dirNFErr;
  247.         }
  248.  
  249.         if (dropLoc.dataHandle)
  250.         {
  251.             OSErr err2 = AEDisposeDesc (&dropLoc);
  252.             if (!err) err = err2;
  253.         }
  254.     }
  255.  
  256.     return err;
  257. }
  258.  
  259. pascal OSErr AddDragItemFlavorTypePromiseHFS
  260.     (DragReference dragRef, ItemReference itemRef,
  261.         OSType fileType, OSType fileCreator, UInt16 fdFlags, FlavorType promisedFlavor)
  262. {
  263.     OSErr err = noErr;
  264.  
  265.     PromiseHFSFlavor phfs;
  266.  
  267.     phfs.fileType            = fileType;
  268.     phfs.fileCreator        = fileCreator;
  269.     phfs.fdFlags            = fdFlags;
  270.     phfs.promisedFlavor        = promisedFlavor;
  271.  
  272.     if (!(err = AddDragItemFlavor
  273.         (dragRef,itemRef,flavorTypePromiseHFS,&phfs,sizeof(phfs),flavorNotSaved)))
  274.     {
  275.         err = AddDragItemFlavor (dragRef,itemRef,promisedFlavor,nil,0,flavorNotSaved);
  276.     }
  277.  
  278.     return err;
  279. }
  280.  
  281. pascal OSErr MakeHFSFlavor
  282.     (short vRefNum, long dirID, ConstStr255Param path, HFSFlavor register *hfsFlavorP)
  283. {
  284.     OSErr err = noErr;
  285.  
  286.     //
  287.     //    canonize the input parameters
  288.     //
  289.  
  290.     if (!(err = FSMakeFSSpec (vRefNum,dirID,path,&(hfsFlavorP->fileSpec))))
  291.     {
  292.         //
  293.         //    get the Finder flags
  294.         //
  295.  
  296.         register CInfoPBPtr cipbp = (CInfoPBPtr) NewPtrClear (sizeof (*cipbp));
  297.         if (!(err = MemError ( )))
  298.         {
  299.             cipbp->hFileInfo.ioVRefNum    = hfsFlavorP->fileSpec.vRefNum;
  300.             cipbp->hFileInfo.ioDirID    = hfsFlavorP->fileSpec.parID;
  301.             cipbp->hFileInfo.ioNamePtr    = hfsFlavorP->fileSpec.name;
  302.  
  303.             if (!(err = PBGetCatInfoSync (cipbp)))
  304.             {
  305.                 hfsFlavorP->fdFlags = cipbp->hFileInfo.ioFlFndrInfo.fdFlags;
  306.  
  307.                 //
  308.                 //    now that we have the Finder flags, use them to
  309.                 //    determine how to fill in the type and creator fields
  310.                 //
  311.  
  312.                 if (hfsFlavorP->fileSpec.parID == fsRtParID)        // is it a volume?
  313.                 {
  314.                     hfsFlavorP->fileCreator        = 'MACS';
  315.                     hfsFlavorP->fileType        = 'disk';
  316.                 }
  317.                 else if (cipbp->hFileInfo.ioFlAttrib & ioDirMask)    // is it a dir?
  318.                 {
  319.                     hfsFlavorP->fileCreator        = 'MACS';
  320.                     hfsFlavorP->fileType        = 'fold';
  321.                 }
  322.                 else                                                // it must be a file
  323.                 {
  324.                     hfsFlavorP->fileCreator        = cipbp->hFileInfo.ioFlFndrInfo.fdCreator;
  325.                     hfsFlavorP->fileType        = cipbp->hFileInfo.ioFlFndrInfo.fdType;
  326.                 }
  327.             }
  328.  
  329.             DisposePtr ((Ptr) cipbp);
  330.             if (!err) err = MemError ( );
  331.         }
  332.     }
  333.  
  334.     return err;
  335. }
  336.  
  337. pascal OSErr GetHFSFlavorFromDragReference
  338.     (DragReference dragRef, ItemReference itemRef, HFSFlavor *hfsFlavor)
  339. {
  340.     OSErr err = noErr;
  341.  
  342.     //
  343.     //    Attempt to get the data. We'll return errors to the caller,
  344.     //    who will be expected to interpret badDragFlavorErr as meaning
  345.     //    there was no flavorTypeHFS data to get.
  346.     //
  347.  
  348.     Size size = sizeof (*hfsFlavor);
  349.     err = GetFlavorData (dragRef,itemRef,flavorTypeHFS,hfsFlavor,&size,0);
  350.  
  351.     if (!err)
  352.     {
  353.         Size minSize = sizeof (*hfsFlavor) - sizeof (hfsFlavor->fileSpec);
  354.         minSize += MinimumBytesForFSSpec (&(hfsFlavor->fileSpec));
  355.         if (size < minSize)
  356.             err = cantGetFlavorErr;
  357.     }
  358.  
  359.     return err;
  360. }
  361.  
  362. static pascal OSErr SetFlavorTypePromiseHFSDropLocation
  363.     (DragReference dragRef, const FSSpec *folder)
  364. {
  365.     OSErr err = noErr;
  366.  
  367.     AliasHandle aliasH;
  368.  
  369.     if (!(err = NewAliasMinimal (folder,&aliasH)))
  370.     {
  371.         HLockHi ((Handle) aliasH);
  372.         if (!(err = MemError ( )))
  373.         {
  374.             Size size = GetHandleSize ((Handle) aliasH);
  375.             if (!(err = MemError ( )))
  376.             {
  377.                 AEDesc dropLoc;
  378.  
  379.                 if (!(err = AECreateDesc (typeAlias,*aliasH,size,&dropLoc)))
  380.                 {
  381.                     OSErr err2;
  382.  
  383.                     err = SetDropLocation (dragRef,&dropLoc);
  384.  
  385.                     err2 = AEDisposeDesc (&dropLoc);
  386.                     if (!err) err = err2;
  387.                 }
  388.             }
  389.         }
  390.  
  391.         DisposeHandle ((Handle) aliasH);
  392.         if (!err) err = MemError ( );
  393.     }
  394.  
  395.     return err;
  396. }
  397.  
  398. static pascal OSErr GetHFSFlavorFromPromise
  399.     (DragReference dragRef, ItemReference itemRef,
  400.         HFSFlavor *hfs, Boolean isSupposedlyFromFindFile)
  401. {
  402.     OSErr             err = noErr;
  403.     PromiseHFSFlavor  phfs;
  404.     Size              size = sizeof (phfs);
  405.  
  406.     err = GetFlavorData
  407.         (dragRef,itemRef,flavorTypePromiseHFS,&phfs,&size,0);
  408.  
  409.     if (!err)
  410.     {
  411.         if (size != sizeof (phfs))
  412.             err = cantGetFlavorErr;
  413.         else
  414.         {
  415.             Boolean isFromFindFile =
  416.                 phfs.promisedFlavor == kPromisedFlavorFindFile;
  417.  
  418.             if (isSupposedlyFromFindFile != isFromFindFile)
  419.                 err = paramErr;
  420.             else
  421.             {
  422.                 size = sizeof (hfs->fileSpec);
  423.                 err = GetFlavorData
  424.                     (dragRef,itemRef,phfs.promisedFlavor,
  425.                         &(hfs->fileSpec),&size,0);
  426.  
  427.                 if (!err)
  428.                 {
  429.                     Size minSize = MinimumBytesForFSSpec
  430.                         (&(hfs->fileSpec));
  431.  
  432.                     if (size < minSize)
  433.                         err = cantGetFlavorErr;
  434.                     else
  435.                     {
  436.                         hfs->fileType     = phfs.fileType;
  437.                         hfs->fileCreator  = phfs.fileCreator;
  438.                         hfs->fdFlags      = phfs.fdFlags;
  439.                     }
  440.                 }
  441.             }
  442.         }
  443.     }
  444.     return err;
  445. }
  446.  
  447. pascal OSErr ReceivePromisedFile
  448.     (DragReference dragRef, ItemReference itemRef, HFSFlavor *hfsFlavor, const FSSpec *folder)
  449. {
  450.     OSErr err = noErr;
  451.  
  452.     if (folder)
  453.         err = SetFlavorTypePromiseHFSDropLocation (dragRef,folder);
  454.  
  455.     if (!err)
  456.     {
  457.         Boolean isSupposedlyFromFindFile = (folder == nil);
  458.         err = GetHFSFlavorFromPromise (dragRef, itemRef, hfsFlavor, isSupposedlyFromFindFile);
  459.     }
  460.  
  461.     return err;
  462. }
  463.  
  464. pascal OSErr BogusFinderEventHandler (const AppleEvent *, AppleEvent *, long)
  465. {
  466.     return noErr; // just drop that bad boy on the floor
  467. }
  468.  
  469. pascal OSErr InstallBogusFinderEventHandler (void)
  470. {
  471.     OSErr err = noErr;
  472.  
  473.     static AEEventHandlerUPP bogusFinderEventHandlerUPP;
  474.  
  475.     if (!bogusFinderEventHandlerUPP)
  476.     {
  477.         bogusFinderEventHandlerUPP =
  478.             NewAEEventHandlerProc (BogusFinderEventHandler);
  479.  
  480.         if (!bogusFinderEventHandlerUPP)
  481.             err = nilHandleErr;
  482.         else
  483.         {
  484.             err = AEInstallEventHandler ('cwin','****',bogusFinderEventHandlerUPP,0,false);
  485.  
  486.             if (err)
  487.             {
  488.                 DisposeRoutineDescriptor (bogusFinderEventHandlerUPP);
  489.                 bogusFinderEventHandlerUPP = nil;
  490.             }
  491.         }
  492.     }
  493.  
  494.     return err;
  495. }
  496.